//#include <iostream>
// run: time -p $exec < tube9.in > out
// opt: 0
// flag: -g
#include <cstdio>
#include <algorithm>

int const maxn = 2200000;
int const maxm = 2000007;
int const maxq = 100007;

struct edge
{
	int from, to, cost, index;
} edges[maxm];

bool deleted_edge[maxm];

int father[maxn];

bool operator<(edge const & a, edge const & b)
{
	return a.cost < b.cost;
}

bool cmp(edge const & a, edge const & b)
{
	return a.from < b.from || (a.from == b.from && a.to < b.to);
}


bool cmp2(edge const & a, edge const & b)
{
	return a.index < b.index;
}

struct query
{
	int opt, x, y, index;
} queries[maxq];

int value[maxn];
int ans[maxq];
int n, m, q, tot;

struct node
{
	int id, max;
	bool rev;
	int parent, child[2];
} memory[maxn];

bool root[maxn];

void push_down(int u)
{
	if (u && memory[u].rev) {
		std::swap(memory[u].child[0], memory[u].child[1]);
		memory[memory[u].child[0]].rev ^= true;
		memory[memory[u].child[1]].rev ^= true;
		memory[u].rev = false;
	}
}

void push_up(int u)
{
	if (!u) return;
	memory[u].max = u;
	if (value[memory[memory[u].child[0]].max] > value[memory[u].max]) memory[u].max = memory[memory[u].child[0]].max;
	if (value[memory[memory[u].child[1]].max] > value[memory[u].max]) memory[u].max = memory[memory[u].child[1]].max;
}

void P(int u)
{
	if (!root[u]) P(memory[u].parent);
	push_down(u);
}

void zig(int u)
{
	int y = memory[u].parent;
	int z = memory[y].parent;
	memory[u].parent = z; memory[y].parent = u;
	memory[y].child[0] = memory[u].child[1]; memory[memory[u].child[1]].parent = y;
	memory[u].child[1] = y;
	if (root[y]) root[y] = false, root[u] = true;
	else {
		if (y == memory[z].child[0]) memory[z].child[0] = u;
		else memory[z].child[1] = u;
	}
	push_up(y);
}
void zag(int u)
{
	int y = memory[u].parent;
	int z = memory[y].parent;
	memory[u].parent = z; memory[y].parent = u;
	memory[y].child[1] = memory[u].child[0]; memory[memory[u].child[0]].parent = y; memory[u].child[0] = y;
	if (root[y]) root[y] = false, root[u] = true;
	else {
		if (y == memory[z].child[0]) memory[z].child[0] = u;
		else memory[z].child[1] = u;
	}
	push_up(y);
}

void splay(int u)
{
	P(u);
	while (!root[u]) {
		int v = memory[u].parent;
		int w = memory[v].parent;
		if (root[v]) {
			if (u == memory[v].child[0]) zig(u);
			else zag(u);
			break;
		}
		if (memory[w].child[0] == v) {
			if (memory[v].child[0] == u) zig(v), zig(u);
			else zag(u), zig(u);
		} else {
			if (memory[v].child[1] == u) zag(v), zag(u);
			else zig(u), zag(u);
		}
	}
	push_up(u);
}

void access(int u)
{
	int v = 0;
	for (; u; v = u, u = memory[u].parent) {
		splay(u);
		root[memory[u].child[1]] = true;
		memory[u].child[1] = v;
		root[memory[u].child[1]] = false;
		push_up(u);
	}
}

void make_root(int u)
{
	access(u);
	splay(u);
	memory[u].rev ^= true;
}

int get_root(int u)
{
	for (access(u), splay(u); memory[u].child[0]; u = memory[u].child[0]);
	return u;
}

void link(int u, int v)
{
	make_root(u);
	memory[u].parent = v;
	access(u);
}

void cut(int u, int v)
{
	make_root(u);
	access(v);
	splay(v);
	root[memory[v].child[0]] = true;
	memory[memory[v].child[0]].parent = 0;
	memory[v].child[0] = 0;
	push_up(v);
}

void init(int n)
{
	for (int i = 0; i <= n; i++) {
		memory[i].parent = memory[i].child[0] = memory[i].child[1] = 0;
		memory[i].id = memory[i].max = i;
		memory[i].rev = false;
		root[i] = true;
		father[i] = i;
	}
}

int query_max(int u, int v)
{
	make_root(u);
	access(v);
	splay(v);
	return memory[v].max;
}

void scan(int & tmp)
{
	char ch = getchar();
	for ( ; ch > '9' || ch < '0'; ch = getchar());
	tmp = 0;
	for ( ; '0' <= ch && ch <= '9'; ch = getchar())
	tmp = tmp * 10 + int(ch) - 48;
}

/*
const int BZ = 30 << 20;
char Buf[BZ + 1], *buf = Buf;

template <class T>
inline void scan(T &a) // method2: for huge input
{
	bool flag = false;
	for (a = 0; *buf < '0' || *buf > '9'; ++buf)
		if (*buf == '-') flag = true;
	for (; *buf >= '0' && *buf <= '9'; buf++)
		a = a * 10 + (*buf - '0');
	if (flag) a = -a;
}
*/

int find_index(int x, int y)
{
	int l = 1, r = m;
	while (true) {
		int mid = (l + r) / 2;
		if (edges[mid].from == x && edges[mid].to == y) return edges[mid].index;
		if (edges[mid].from < x || (edges[mid].from == x && edges[mid].to < y))
			l = mid + 1;
		else
			r = mid - 1;
	}
}

int get_father(int x)
{
	return father[x] == x ? x : father[x] = get_father(father[x]);
}

int main()
{
/*
	std::fread(Buf, 1, BZ, stdin); // method2
*/

	scan(n); scan(m); scan(q);

	for (int i = 1; i <= m; i++) {
		scan(edges[i].from);
		scan(edges[i].to);
		scan(edges[i].cost);
		if (edges[i].from > edges[i].to) std::swap(edges[i].from, edges[i].to);
	}
	std::sort(edges + 1, edges + m + 1);
	for (int i = 1; i <= m; i++) edges[i].index = i;

	std::sort(edges + 1, edges + m + 1, cmp);

#ifdef __DEBUG
	for (int i = 1; i <= m; i++) std::cerr << edges[i].from  << ' ' << edges[i].to << ' ' << edges[i].cost << ' ' << edges[i].index << '\n';
#endif

	for (int i = 0; i < q; i++) {
		scan(queries[i].opt);
		scan(queries[i].x);
		scan(queries[i].y);
		if (queries[i].x > queries[i].y) std::swap(queries[i].x, queries[i].y);


#ifdef __DEBUG
		std::cerr << "query: " << queries[i].opt << ' ' << queries[i].x << ' ' << queries[i].y << "  t = " << t << '\n';
#endif

		if (queries[i].opt == 2) {
			int t = queries[i].index = find_index(queries[i].x, queries[i].y);
			deleted_edge[t] = true;
		}
	}

	std::sort(edges + 1, edges + m + 1, cmp2);

#ifdef __DEBUG
	for (int i = 1; i <= m; i++) std::cerr << edges[i].from  << ' ' << edges[i].to << ' ' << edges[i].cost << ' ' << edges[i].index << '\n';
#endif

	init(n + m);

	for (int i = 1; i <= m; i++) value[n + i] = edges[i].cost;

	// init graph construct lct
	for (int i = 1; i <= m; i++) {
		if (deleted_edge[i]) continue;
		int f1 = get_father(edges[i].from);
		int f2 = get_father(edges[i].to);
		if (f1 == f2) continue;
//		if (get_root(edges[i].from) == get_root(edges[i].to)) continue;
		link(edges[i].from, n + i);
		link(edges[i].to,   n + i);
		father[f1] = f2;
	}

	for (int i = q - 1; i >= 0; i--) {
		if (queries[i].opt == 1) {
			ans[tot++] = value[query_max(queries[i].x, queries[i].y)];
		} else {
			int t = query_max(queries[i].x, queries[i].y);
			int ti = queries[i].index;
#ifdef __DEBUG
			std::cerr << "ti  = " << ti << '\n';
#endif
			if (value[t] > edges[ti].cost) {
				cut(t, edges[t - n].from);
				cut(t, edges[t - n].to);
				link(ti + n, edges[ti].from);
				link(ti + n, edges[ti].to);
			}
		}
	}

	for (int i = tot - 1; i >= 0; i--)
		std::printf("%d\n", ans[i]);
}

